module;
#include <type_traits>  // for true_type, false_type, and void_t
#include <iostream>
#include <vector>

export module Code_19_6_2;

#define DEFINE_HAS_TYPE(MemType) \
template<typename, typename = std::void_t<>> \
struct HasTypeT_##MemType : std::false_type {};  \
template<typename T> \
struct HasTypeT_##MemType<T, std::void_t<typename T::MemType>> : std::true_type { }; 

// intentionally skipped

DEFINE_HAS_TYPE(value_type);
DEFINE_HAS_TYPE(char_type);

export
namespace Code_19_6_2 {

    void run()
    {
        std::cout << "int::value_type: "              << HasTypeT_value_type<int>::value << '\n';
        std::cout << "std::vector<int>::value_type: " << HasTypeT_value_type<std::vector<int>>::value << '\n';
        std::cout << "std::iostream::value_type: "    << HasTypeT_value_type<std::iostream>::value << '\n';
        std::cout << "std::iostream::char_type: "     << HasTypeT_char_type<std::iostream>::value << '\n';
    }
}
